/*
 * Created on Wed Jun 06 2018 by Ronnie Ren (zhaosong.ren) from Accenture
 *
 * Copyright (c) 2018 DingXing information & technology limited company.
 */

import { Injectable } from "@angular/core";
import { UserDto } from "../dto/user.dto";
import { User } from "../transform/user";
import { Observable } from 'rxjs/Observable';
import { SqliteService } from "../../services/sqliteDB/sqlite.service";
import { CurdService } from "./curd.service";
import { BillService } from "./bill.service";
import { JsonMappingUtil } from "../json-mapping-util";
import { WorkOrderService } from "./work-order.service";
import {WorkOrder} from "../transform/work-order";
import {WorkOrderDto} from "../dto/work-orders.dto";
import {ConditionFetch} from "../../services/sqliteDB/condition-fetch";
import { SecureStorageService } from '../../../shared/services/secure-storage.services';
import { HttpService } from 'http-service';
import { API } from "../../../shared/models/api-path-extension";

@Injectable()
export class UserService {

  private static pageSize = 5;
  private api: API;
  constructor(
    private sqliteService: SqliteService,
    private sqliteUtilService: CurdService,
    private workOrderService: WorkOrderService,
    private billService: BillService,
    private storage: SecureStorageService,
    private httpService: HttpService
  ) {
    this.api = new API();
  }

  fetchUsersByPage(page: number): Observable<Array<User>> {

    let userDto = new UserDto();
    let sql = `select * from ${userDto.table().tableName} order by theToppestChargeLevel desc,totalUnPaidAmount desc limit `
      + ` ${UserService.pageSize} offset ${page * UserService.pageSize}`;
    console.log(sql);
    return Observable.fromPromise(
      this.sqliteService.executeSqlWithResults<UserDto>(sql, UserDto)
    )
      .map((users: Array<UserDto>) => {
        return users.map((aUserDto) => new User(aUserDto));
      });
  }

  loadBills(user: User): Observable<boolean> {
    return this.billService.fetchBillsByUserId(user.id).do((bills) => user.bills = bills).map(() => true);
  }

  loadWorkOrder(user: User): Observable<boolean> {
    return this.workOrderService.fetchInProgressWorkOrderByUserId(user.id).do((workOrders) => user.workOrders = workOrders)
      .map(() => true);
  }

  getUserArray(condition: ConditionFetch, orderBy: Array<string> = []): Observable<Array<UserDto>> {
    return Observable.fromPromise(this.sqliteUtilService.fetchByCondition(UserDto,
      condition, orderBy))
      .map((results) => {
        return Array.from(results["results"]);
      })
      .map((results) => {
        return results.map((row) => {
          let userDto = new UserDto();
          JsonMappingUtil.MappingAllProp(row, userDto);
          return userDto;
        });
      });
  }

  fetchUsesById(userId: string, fetchBillsAndWorkOrders: boolean = false): Observable<User> {
    let userDto = new UserDto();

    return Observable.fromPromise(
      this.sqliteService.executeSqlWithResults<UserDto>(`select * from ${userDto.table().tableName} where id = '${userId}'`, UserDto)
    ).map((rows: Array<{}>) => {
      return rows.map((row) => {
        let user = new User({});
        JsonMappingUtil.MappingAllProp(row, user);
        return user;
      });
    })
      .flatMap((users: Array<User>) => {
        console.log(users);
        if (fetchBillsAndWorkOrders) {
          let user = users[0];
          return this.loadBills(user).flatMap(() => this.loadWorkOrder(user))
            .map(() => user);
        }
        return Observable.of(users[0]);
      });
  }

  getUser(): Promise<any> {
    return new Promise((res, rej) => {
      this.storage.get('userInfo').subscribe((resp) => {
        if (res) {
          res(resp['data']);
        } else {
          this.httpService.get(this.api.path({ path: "userInfo" }).baseURL, null).subscribe((response) => {
            this.storage.set('userInfo', response);
            res(response["data"]);
          });
        }
      });
    });
  }
}
